from flask import current_app, abort, render_template, session, g, jsonify, request

from info import db
from info.common import user_login_data
from info.constants import CLICK_RANK_MAX_NEWS
from info.models import News, User, Comment
from info.modules.news import news_blu
# 显示新闻详情页面
from info.utils.response_code import RET, error_map

'''
技术选型：新闻页面需要seo ,采用后端渲染
具体逻辑：
１．绑定动态url
２．根据新闻的id 获取新闻模型
３．根据新闻模型进行魔板替换
'''


@news_blu.route('/<int:news_id>')
@user_login_data
def news_ditail(news_id):
    # 根据新闻的id 获取新闻
    news = None
    try:
        news = News.query.get(news_id)
    except BaseException as e:
        current_app.logger.error(e)

    if not news:
        return abort(404)

    # 让新闻的点击量＋１
    news.clicks += 1

    # 查询新闻，按照点击量的倒序排列取前面１０条
    rank_list = []
    try:
        rank_list = News.query.order_by(News.clicks.desc()).limit(CLICK_RANK_MAX_NEWS).all()

    except BaseException as e:
        current_app.logger.error(e)

    rank_list = [news.to_basic_dict() for news in rank_list]

    # 查询当前用户是否收藏了该新闻
    is_collected = False
    user = g.user
    if user:
        if news in user.collection_news:
            is_collected = True


    # 查询当期用户的所有评论，传到模板中
    comments= Comment.query.filter(Comment.news_id == news_id).order_by(Comment.create_time.desc()).all()


    # 查询当前页面面，用户对那些评论点过赞
    comments_list = []
    if user :
        for comment in comments:
            is_like = False
            comment_dict = comment.to_dict()
            if comment in user.like_comments:
                is_like = True
            comment_dict['is_like'] = is_like
            # 将评论字典加入列表中
            comments_list.append(comment_dict)



    # 将用户登录的信息传递到模板中，全局刷新，我们采取后端渲染
    user = g.user.to_dict() if g.user else None

    # 将模型数据传到模板中,模板替换
    return render_template('news/detail.html', news=news.to_dict(), rank_list=rank_list, user=user,is_collected=is_collected,comments=comments_list)


'''
技术选型：收藏和取消收藏，是局部刷新，采用前端渲染
具体逻辑：
1.1请求方式post　没有提交为什么用post 因为收藏是建立在用户和新闻的多对对的关系
收藏表中有news_id 和user_id ，接口函数需要俩个数据，不能放在url里面，get不完全．

1.2用户的id 是保存到ｓession 中，获取news_id 就行
2.建立收藏和取消收藏的关系用一个action 来确定
3.响应的方式：局部刷新响应的方式采取json

'''

# 收藏和取消收藏
@news_blu.route('/news_collect', methods=['POST'])
@user_login_data
def news_collect():
    # 判断用户有没有登录
    user = g.user
    if not user:
        return jsonify(errno=RET.SESSIONERR, errmsg=error_map[RET.SESSIONERR])

    # 获取参数
    news_id = request.json.get('news_id')
    action = request.json.get('action')

    # 校验参数
    if not all([news_id, action]):
        return jsonify(errno=RET.PARAMERR, errmsg=error_map[RET.PARAMERR])

    try:
        news_id = int(news_id)
    except BaseException as e:
        return jsonify(errno=RET.PARAMERR, errmsg=error_map[RET.PARAMERR])

    if action not in ['collect', 'cancel_collect']:
        return jsonify(errno=RET.PARAMERR, errmsg=error_map[RET.PARAMERR])
    try:
        news = News.query.get(news_id)
    except BaseException as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg=error_map[RET.DBERR])
    if not news:
        return jsonify(errno=RET.NODATA, errmsg=error_map[RET.NODATA])

    #  根据action 建立user_id 和news_id 来建立关系
    if action == 'collect':  # 收藏
        if news not in user.collection_news:
            user.collection_news.append(news)
    else:  # 取消收藏
        if news in user.collection_news:
            user.collection_news.remove(news)
    # 返回json 的结果
    return jsonify(errno=RET.OK, errmsg=error_map[RET.OK])


# 评论和回复
@news_blu.route('/news_comment',methods=['POST'])
@user_login_data
def news_comment():
    # 判断用户是否登录
    user = g.user
    if not user:
        return jsonify(errno=RET.SESSIONERR,errmsg=error_map[RET.SESSIONERR] )
    # 获取参数
    comment_content = request.json.get('comment')
    news_id = request.json.get('news_id')
    parent_id = request.json.get('parent_id')

    # 校验参数,转化参数类型
    if not all([comment_content,news_id]):
        return jsonify(errno=RET.PARAMERR,errmsg="1")
    try:
        news_id = int(news_id)
    except BaseException as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.PARAMERR,errmsg="2" )
    # 判断新闻是否存在
    try:
        news = News.query.get(news_id)
    except BaseException as e :
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR,errmsg="3" )

    if not news:
        return jsonify(errno=RET.NODATA,errmsg="4" )

    # 生成评论的模型
    comment = Comment()
    comment.content = comment_content
    comment.news_id = news_id
    comment.user_id = user.id
    if parent_id:
        try:
            parent_id = int(parent_id)
        except BaseException as e :
            current_app.logger.error(e)
            return jsonify(errno=RET.PARAMERR,errmsg="5" )
        comment.parent_id = parent_id

    # 添加到数据库中中
    try:
        db.session.add(comment)
        db.session.commit() # 虽然sqlalchemy_commit_on_teardown可以自动提交，但是此处需要然会的评论主键ＩＤ．多以要先主动生成
    except BaseException as e:
        current_app.logger.error(e)
        db.session.rollback()
        return jsonify(errno=RET.DBERR,errmsg=error_map[RET.DBERR])
    # json 结果返回
    return jsonify(errno=RET.OK,errmsg=error_map[RET.OK],data=comment.to_dict() )


'''
１．技术选型：点赞和取消点在，局部刷新，采用前端渲染
２．具体逻辑：
    a:获取参数＆校验参数
    b:根据传递的数据建立/取消用户和评论的关系
    c:将结果json返回
    
接口设计：url:/news/comment_like
请求参数：comment_id 评论de id 和　action add/remove
请求方式post
响应形式：json
'''
# 点赞/取消点赞
@news_blu.route('/comment_like',methods=['POST'])
@user_login_data
def comment_like():
    # 判断用户是否登录
    user =g.user
    if not user:
        return jsonify(errno=RET.SESSIONERR,errmsg='1' )

    # 获取参数
    comment_id = request.json.get('comment_id')
    action = request.json.get('action')
    # 校验参数
    if not all([comment_id,action]):
        return jsonify(errno=RET.DBERR,errmsg='2' )

    try:
        comment_id = int(comment_id)
    except BaseException as e:
        return jsonify(errno=RET.PARAMERR,errmsg='3')
    if action not in ['add','remove']:
        return jsonify(errno=RET.PARAMERR,errmsg='4' )

    # 从数据库中获取评论
    try:
        comment = Comment.query.get(comment_id)
    except BaseException as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR,errmsg='6' )

    if not comment:
        return jsonify(errno=RET.NODATA,errmsg='7' )

    # 根据action 执行处理（user_id和comment_id的建立和取消关系）

    if action == 'add': # 点赞
        if comment not in user.like_comments:
            user.like_comments.append(comment)
            comment.like_count += 1
    else:# 取消点赞
        if comment in user.like_comments:
            user.like_comments.remove(comment)
            comment.like_count -= 1

    return jsonify(errno=RET.OK,errmsg=error_map[RET.OK] )
























